import { useBluetoothStore } from '@/store';

interface BluetoothDevice {
	deviceId : string
	name : string
	localName ?: string
	aliasName ?: string
	connected : boolean
	connectedAt ?: number
	config ?: any
	notifying ?: boolean
}

interface BluetoothProtocolConfig {
	BluetoothProtocol : string
}

class BluetoothManager {
	private store : ReturnType<typeof useBluetoothStore>
	private deviceMap : Record<string, any> = {}
	private isDiscovering : boolean = false
	private connectedDevices : Record<string, BluetoothDevice> = {}
	private aliasMap : Record<string, string> = {}
	private _stopDiscoveryMethod ?: () => void

	constructor() {
		this.store = useBluetoothStore()
		this.aliasMap = this.getAliasMap()
		this.initListeners()
	}

	/** ===================== 初始化全局监听 ===================== */
	private initListeners() : void {
		// 监听蓝牙适配器状态变化
		uni.onBluetoothAdapterStateChange((res) => {
			console.log("📡 蓝牙适配器状态变化:", res)
			this.store.setAdapterState(res)
		})

		// 监听设备连接状态变化
		uni.onBLEConnectionStateChange((res) => {
			const { deviceId, connected } = res
			console.log("🔗 蓝牙连接状态变化:", res)

			if (this.connectedDevices[deviceId]) {
				this.connectedDevices[deviceId].connected = connected
			}

			this.store.updateConnection({ deviceId, connected })

			if (connected) {
				this.enableNotify(deviceId)
			}
		})

		// 监听蓝牙特征值变化（接收数据）
		uni.onBLECharacteristicValueChange(async (res) => {
			console.log(res)
			const hex = this.ab2hex(res.value)

			console.log(hex)

			const deviceInfo = this.store.connectedDevices[res.deviceId]
			if (!deviceInfo?.config) return

			const backData = await this.getDataByBluetoothProtocol(
				hex,
				deviceInfo.config.BluetoothProtocol
			)

			console.log(backData)

			uni.$emit("send:bluetooth-data", {
				num: backData,
				deviceInfo
			})
		})
	}

	private getDataByBluetoothProtocol(hexStr : string, BluetoothProtocol : string) : number | null {
		let parsedValue : number | null = null
		let dataHex : string | null = null

		switch (BluetoothProtocol) {
			case "YBKC_Sanhe_5101": // 三和游标卡尺
				dataHex = hexStr.slice(8)
				console.log("原始HEX:", dataHex)
				const str = dataHex.substring(dataHex.length - 2)
				let raw = parseInt(dataHex.slice(0, 6), 16)

				if (raw & 0x800000) {
					raw = raw - 0x1000000
				}

				console.log("解析DEC:", raw)
				parsedValue = str == '01' ? -(raw / 100) : raw / 100
				break

			case "QFB_Sanhe_001": // 三和千分表
				dataHex = hexStr.slice(8)
				const str2 = dataHex.substring(dataHex.length - 2)
				let raw2 = parseInt(dataHex.slice(0, 6), 16)

				if (raw2 & 0x800000) {
					raw2 = raw2 - 0x1000000
				}

				console.log(raw2)
				parsedValue = str2 == '01' ? -(raw2 / 10000) : raw2 / 10000
				break

			default:
				parsedValue = null
				break
		}

		return parsedValue
	}

	/** ===================== 初始化蓝牙 ===================== */
	openBluetooth() : Promise<any> {
		return new Promise((resolve, reject) => {
			uni.openBluetoothAdapter({
				success: (res) => {
					console.log("✅ 蓝牙适配器已初始化")
					this.store.setAdapterOpen(true)
					resolve({ ...res, status: 0 })
				},
				fail: (err) => {
					console.error("❌ 初始化失败:", err)
					uni.showToast({
						title: "请打开蓝牙权限",
						icon: "none"
					})
					reject(err)
				}
			})
		})
	}

	/** ===================== 蓝牙扫描 ===================== */
	startDiscovery(callback ?: (devices : BluetoothDevice[]) => void, options = { allowDuplicatesKey: true }) : void {
		let _that = this;
		console.log(this.isDiscovering);
		if (this.isDiscovering) {
			console.warn("⚠️ 正在扫描中")
			return
		}

		this.isDiscovering = true
		this.deviceMap = {}
		this.store.clearDevices()

		// 移除之前的监听
		this.removeDeviceListener()

		// 设置设备发现监听
		this.listenDeviceFound((devices) => {
			callback && callback(devices)
		})

		uni.startBluetoothDevicesDiscovery({
			allowDuplicatesKey: options.allowDuplicatesKey,
			success: () => {
				console.log("✅ 开始扫描蓝牙设备")
				console.log(_that.isDiscovering);
				console.log(uni.$utils.$bluetooth.isDiscovering);

				_that._stopDiscoveryMethod = () => {
					console.log("🛑 停止扫描")
					_that.isDiscovering = false
					uni.stopBluetoothDevicesDiscovery()
					_that.removeDeviceListener()
				}
			},
			fail: (err) => {
				console.error("❌ 扫描失败:", err)
				_that.isDiscovering = false
				_that.removeDeviceListener()
			}
		})
	}

	stopDiscovery() : void {
		if (!this.isDiscovering) return
		// this.isDiscovering = false
		if (this._stopDiscoveryMethod) {
			this._stopDiscoveryMethod()
		}
	}

	private listenDeviceFound(callback ?: (devices : BluetoothDevice[]) => void) : void {
		uni.onBluetoothDeviceFound((res) => {
			const devices = (res as any).devices || [(res as any).device] || []
			const validDevices = devices.filter((d : any) => d.name || d.localName)
			callback && callback(validDevices)
		})
	}

	private removeDeviceListener() : void {
		// uni.offBluetoothDeviceFound()
	}

	/** ===================== 连接与断开 ===================== */
	connectDevice(
		device : BluetoothDevice,
		basicInfo : BluetoothProtocolConfig,
		successCallback ?: () => void,
		failCallback ?: (err : any) => void
	) : void {
		if (!device.deviceId) return

		const { deviceId } = device
		console.log(`🔗 尝试连接设备: ${deviceId}`)

		uni.createBLEConnection({
			deviceId,
			success: () => {
				console.log(`✅ 连接成功: ${deviceId}`)
				const aliasName = this.getDeviceAlias(deviceId)

				const connectedDevice : BluetoothDevice = {
					...device,
					config: basicInfo,
					connected: true,
					connectedAt: Date.now(),
					aliasName: aliasName || device.name
				}

				this.connectedDevices[deviceId] = connectedDevice
				this.store.addConnectedDevice(connectedDevice)

				this.stopDiscovery()
				successCallback && successCallback()
			},
			fail: (err) => {
				failCallback && failCallback(err)
				console.error(`❌ 连接失败 (${deviceId}):`, err)
				uni.showToast({
					title: "连接失败",
					icon: "none"
				})
			}
		})
	}

	disconnectDevice(deviceId : string, callback ?: () => void) : void {
		if (!deviceId) {
			uni.showToast({
				title: "无效设备ID",
				icon: "none"
			})
			return
		}

		uni.closeBLEConnection({
			deviceId,
			success: () => {
				console.log(`🛑 已断开设备: ${deviceId}`)

				// 从连接池中移除
				if (this.connectedDevices[deviceId]) {
					delete this.connectedDevices[deviceId]
				}

				this.store.updateConnection({ deviceId, connected: false })
				this.store.removeConnectedDevice(deviceId)

				callback && callback()
			},
			fail: (err) => {
				console.error(`❌ 断开失败 (${deviceId}):`, err)
			}
		})
	}

	isConnected(deviceId : string) : boolean | Promise<boolean> {
		if (!deviceId) return false

		const localStatus = this.connectedDevices[deviceId]?.connected
		if (localStatus) return true

		return new Promise((resolve) => {
			uni.getConnectedBluetoothDevices({
				services: [], // 添加services属性，为空数组表示获取所有服务的设备
				success: (res) => {
					const found = res.devices.some(d => d.deviceId === deviceId)
					resolve(found)
				},
				fail: () => resolve(false)
			})
		})
	}

	/** ===================== 别名管理 ===================== */
	private getAliasMap() : Record<string, string> {
		try {
			return this.aliasMap || JSON.parse(uni.getStorageSync('bluetooth_alias_map') || '{}')
		} catch (e) {
			return {}
		}
	}

	private saveAliasMap(map : Record<string, string>) : void {
		try {
			this.aliasMap = map
			uni.setStorageSync('bluetooth_alias_map', JSON.stringify(map))
		} catch (e) {
			console.error('保存别名失败:', e)
		}
	}

	getDeviceAlias(deviceId : string) : string | null {
		return this.aliasMap[deviceId] || null
	}

	setDeviceAlias(deviceId : string, aliasName : string) : void {
		if (!deviceId) return

		const aliasMap = this.getAliasMap()
		aliasMap[deviceId] = aliasName
		this.saveAliasMap(aliasMap)

		if (this.connectedDevices[deviceId]) {
			this.connectedDevices[deviceId].aliasName = aliasName
		}

		this.store.updateDeviceAlias({ deviceId, aliasName })
	}

	// 补充 getState 方法（非鸿蒙通过适配器状态获取）
	getState() {
		return this.store.adapterState
	}

	/** ===================== 启用通知 ===================== */
	private enableNotify(deviceId : string) : void {
		if (!deviceId) return

		this.connectedDevices[deviceId].notifying = true

		setTimeout(() => {
			uni.getBLEDeviceServices({
				deviceId,
				success: (res) => {
					const services = res.services.filter(s => s.isPrimary)
					this.subscribeNext(deviceId, services, 0)
				},
				fail: (e) => console.error(`❌ 获取服务失败(${deviceId})`, e)
			})
		}, 300)
	}

	private subscribeNext(deviceId : string, services : any[], index : number) : void {
		if (index >= services.length) return

		uni.getBLEDeviceCharacteristics({
			deviceId,
			serviceId: services[index].uuid,
			success: (res) => {
				const chars = res.characteristics || []
				for (let c of chars) {
					if (c.properties.notify) {
						uni.notifyBLECharacteristicValueChange({
							state: true,
							deviceId,
							serviceId: services[index].uuid,
							characteristicId: c.uuid,
							success: () => console.log(`✅ 启用通知(${deviceId})`),
						})
					}
				}
				this.subscribeNext(deviceId, services, index + 1)
			},
			fail: (e) => console.error("❌ 获取特征失败:", e)
		})
	}

	/** ===================== 工具函数 ===================== */
	private ab2hex(buffer : ArrayBuffer) : string {
		return Array.from(new Uint8Array(buffer))
			.map(b => ("00" + b.toString(16)).slice(-2))
			.join("")
	}

	destroy() : void {
		this.stopDiscovery()
		this.destroyListeners()
		this.deviceMap = {}
		this.connectedDevices = {}
	}

	private destroyListeners() : void {
		uni.offBluetoothAdapterStateChange()
		uni.offBLEConnectionStateChange()
		uni.offBLECharacteristicValueChange()
	}
}

/** 单例导出 */
let instance : BluetoothManager | null = null
export function m_initBluetooth() : BluetoothManager {
	if (!instance) instance = new BluetoothManager()
	return instance
}